package models

import (
	"bigdevops/src/common"
	"fmt"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

// 工作流 审批流
type Process struct {
	Model        // 不用每次写ID 和 createAt了
	Name  string `json:"name" gorm:"uniqueIndex;type:varchar(100);comment:流程名称，支持使用通配符*进行模糊搜索" `
	//Creator User   `json:"Creator" `
	UserID uint
	//FlowNodes     []FlowNode `json:"flowNodes" gorm:"foreignKey:ProcessRefer"`
	// 一对多关系 https://gorm.io/zh_CN/docs/has_many.html
	FlowNodes []FlowNode `json:"flowNodes" `

	FlowNodeStr    string `json:"flowNodeStr" gorm:"-"` //给前端表格
	Key            string `json:"key" gorm:"-"`         //给前端表格
	CreateUserName string `json:"createUserName" gorm:"-"`
}

// 流中的每个节点
type FlowNode struct {
	Model
	ProcessID         uint   // 属于哪个流程
	Type              string `json:"type" gorm:"comment: 起始节点 审批节点 执行节点 结束节点"`
	DefineUserOrGroup string `json:"defineUserOrGroup"  gorm:"comment: 期望的人或者组 userName or RoleName"`
	// 真实执行或认领的人
	ActualUser        string `json:"actualUser"  gorm:"-"`
	OutPut            string `json:"outPut" gorm:"-"` // 审批的结果 ，执行的输出
	EndTime           string `json:"endTime" gorm:"-"`
	IsPassOrIsSuccess bool   `json:"isPassOrIsSuccess" gorm:"-"` // 审批的结果 或执行的结果

}

func (obj *FlowNode) UpdateOne() error {
	return Db.Where("id = ?", obj.ID).Updates(obj).Error

}

func (obj *FlowNode) DeleteOne() error {

	return Db.Select(clause.Associations).Unscoped().Delete(obj).Error

}

func (obj *Process) Create() error {
	return Db.Create(obj).Error

}
func (obj *Process) DeleteOne() error {

	return Db.Select(clause.Associations).Unscoped().Delete(obj).Error

}

func DeleteProcessOneByInstanceId(iid string) error {

	return Db.Select(clause.Associations).Unscoped().Where("instance_id = ?", iid).Delete(&Process{}).Error
}

func (obj *Process) CreateOne() error {
	return Db.Create(obj).Error

}

func (obj *Process) UpdateOne() error {
	return Db.Where("id = ?", obj.ID).Updates(obj).Error

}

func (obj *Process) UpdateFlowNodes(nodes []FlowNode) error {

	return Db.Model(obj).Association("FlowNodes").Replace(nodes)

}

func (obj *Process) FillFrontAllData() {
	dbUser, _ := GetUserById(int(obj.UserID))
	if dbUser != nil {
		obj.CreateUserName = dbUser.Username
	}

	obj.Key = fmt.Sprintf("%d", obj.ID)

	for _, node := range obj.FlowNodes {

		oneNode := fmt.Sprintf("[%s : %s] ", common.FLOW_TYPE_MAP[node.Type], node.DefineUserOrGroup)
		if obj.FlowNodeStr != "" {
			obj.FlowNodeStr = fmt.Sprintf("%s->%s", obj.FlowNodeStr, oneNode)
		} else {
			obj.FlowNodeStr = oneNode
		}

	}

}

func GetProcessCount() int {
	var count int64
	Db.Table("processes").Count(&count)
	return int(count)
}

func GetProcessAllWithLimitOffset(limit, offset int) (objs []*Process, err error) {
	err = Db.Preload("FlowNodes").Limit(limit).Offset(offset).Find(&objs).Error
	return
}

func GetProcessByLevel(level int) (objs []*Process, err error) {
	err = Db.Where("level = ?", level).Preload("OpsAdmins").Find(&objs).Error
	return
}

// select * from ecs where
func GetProcessByIdsWithLimitOffset(ids []int, limit, offset int) (objs []*Process, err error) {
	err = Db.Limit(limit).Offset(offset).Find(&objs, ids).Error
	return
}

func GetProcessByInstanceId(instanceId string) (*Process, error) {

	var dbObj Process
	err := Db.Where("instance_id = ?", instanceId).Preload("FlowNodes").First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("Process不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}

func GetProcessById(id int) (*Process, error) {

	var dbObj Process
	err := Db.Where("id = ?", id).Preload("FlowNodes").First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("Process不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}
